Time Series Models on DOGE Coin Data

Arshak Parsa

2023-11-22

هدف این ارائه

قراره مدل های مختلف سری زمانی رو به داده های دوج کوین برازش کنیم!

library(knitr)

اینا همش کلاهبرداریه!

اینا واقعیه

Ritvik Kharkar

این داداشمون اسمش ریتویک خارکار هست که ویدیو های سری زمانی ایشون رو می تونید تو یوتیوب رایگان ببینید! یکی دوره های پولسازی آشغالشو میلیونی میفروشه از اون طرف یکی دیگه به رایگان بهترین مطالب رو به اشتراک میزاره!

چطور داده دانلود کنیم؟

دستور زیر رو در لینوکس اجرا کنید تا داده ها از نوبیتکس دانلود بشه

curl 'https://api.nobitex.ir/market/udf/history?
symbol=DOGEIRT&resolution=D&to=1862230967'
-o DOGEIRT-D.json

با تغییر resolution و symbol می تونید داده‌های متفاوت بگیرید ، مثلاً symbol=BTCIRT داده بیتکوین میده

تبدیل json به csv

import json
import pandas as pd
file = 'DOGEIRT-D'
with open(file+'.json') as train_file:
    dict1 = json.load(train_file)

# converting json dataset from dictionary to dataframe
df = pd.DataFrame(data=dict1)
df = df.drop('s', axis=1)
df['t'] = pd.to_datetime(df['t'],unit='s')
df = df.set_index('t')
df.index = pd.DatetimeIndex(df.index).to_period('D')
df.to_csv(file+'.csv')

اینا کد پایتونه، از اسلاید بعد همه کد ها تو R هست

بارگذاری داده ها در R

d = read.csv("DOGEIRT-D.csv")
d$t = as.Date(d$t)
kable(head(d,2))
t o h l c v
2020-12-23 105.2 105.2 105.2 105.2 3490
2020-12-24 117.8 121.5 117.8 121.5 3469
kable(tail(d,2))
t o h l c v
1534 2025-03-05 18231.0 19700 17850 17912.2 8579054
1535 2025-03-06 17912.2 18360 17300 18313.7 3591583

تبدیل تاریخ به اعداد

df = data.frame(t = as.numeric(d[,1]-d[1,1]+1),c = d$c)
head(df)
  t     c
1 1 105.2
2 2 121.5
3 3 123.1
4 4 122.0
5 5 122.0
6 6 118.9

رسم داده ها

library(plotly)
d %>% plot_ly(x = ~t, type="candlestick",
          open = ~o, close = ~c,
          high = ~h, low = ~l) 

چطور مدل ها را مقایسه کنیم؟

  • ارزیابی بلند مدت

  • ارزیابی کوتاه مدت

Forecast Accuracy Measures

\(P_i\) مقدار پیش بینی شده و \(A_i\) مقدار واقعی هست.

\[MSE = \frac{1}{n}\sum_{i=1}^{n}(A_i-P_i)^2\] \[RMSE = \sqrt{MSE}\] \[MAD = \frac{1}{n}\sum_{i=1}^{n}|A_i-P_i|\]

فعلا آخرین قیمت closed price را به عنوان متغییر پاسخ در نظر میگیریم.

یک تابع برای ارزیابی بلند مدت

library(zeallot)
res_prep = function(pred,lpred,lfun){
  res = matrix(nrow = length(lfun),ncol = length(lpred))
  rownames(res) = names(lfun)
  colnames(res) = names(lpred)
  colnames(pred) = names(lpred)
  for (i in 1:length(lfun)) {
    res[i,] = apply(pred,2,FUN = lfun[[i]])
  }
  return(list(pred = pred, res = res))
}

LTE = function(lpred,data,xname="t",yname="c",percent=0.8) {
  tr = head(data,round(nrow(data)*percent))
  ts = tail(data,nrow(data)-nrow(tr))
  
  extra.info = list()
  pred = matrix(nrow = nrow(ts))
  yind = which(colnames(ts)==yname)
  for (n in names(lpred)){
    lpred.out = lpred[[n]](tr,ts[,-yind,drop=FALSE])
    pred = cbind(pred,lpred.out[["pred"]])
    extra.info[[n]] = lpred.out[["extra.info"]]
  }
  pred = pred[,-1,drop=FALSE]
  
  lfun = list(RMSE=function(x) sqrt(mean((x-ts[,yname])^2)),MAD=function(x) mean(abs(x-ts[,yname])))
  c(pred,res) %<-% res_prep(pred,lpred,lfun)
  
  # Plot 
  fx = as.formula(paste("~",xname))
  fy = as.formula(paste("~",yname))
  fig = plot_ly(mode="lines", type = "scatter")%>%
  add_trace( data=tr, x = fx, y = fy,name = "train")%>%
  add_trace(data=ts, x = fx, y = fy,name = "test")
  
  for (n in colnames(pred))
    fig = fig %>% add_trace(x=ts[,xname],y=pred[,n],name = n)
  return (list(results = res, fig=fig, extra.info = extra.info))
}

ارزیابی کوتاه مدت؟

در اینجا از K-fold Cross Validation نمی‌توان استفاده کرد.

باید از Rolling Cross Validation استفاده کنید که به دو روش sliding و expanding می تونه انجام بشه!

اما ممکنه بپرسید که اصلا Cross Validation چی هست؟!

K-fold cross-validation

Rolling cross-validation

یک تابع برای ارزیابی کوتاه مدت

STE = function(lpred,data,xname="t",yname="c",startp=0.97,sliding.time=30,is.plot=TRUE) {
  tr = head(data,round(nrow(data)*startp))
  ts = tail(data,nrow(data)-nrow(tr))
  
  fx = as.formula(paste("~",xname))
  fy = as.formula(paste("~",yname))
  fig.base = plot_ly(mode="lines", type = "scatter")%>%
  add_trace( data=tr, x = fx, y = fy,name = "train")%>%
  add_trace(data=ts, x = fx, y = fy,name = "test")
  
  pred.expand = matrix(nrow = nrow(ts),ncol = length(lpred))
  pred.slide = matrix(nrow = nrow(ts), ncol = length(lpred))
  yind = which(colnames(ts)==yname)
  for (i in 1:nrow(ts)){ 
    for (j in 1:length(lpred)){
      pred.slide[i,j] = lpred[[j]](tail(tr,sliding.time),ts[i,-yind,drop=FALSE])[["pred"]]
      pred.expand[i,j] = lpred[[j]](tr,ts[i,-yind,drop=FALSE])[["pred"]]
    }
    tr = rbind(tr,ts[i,])
  }
  
  lfun = list(RMSE=function(x) sqrt(mean((x-ts[,yname])^2)),MAD=function(x) mean(abs(x-ts[,yname])))
  c(pred.expand,res.expand) %<-% res_prep(pred.expand,lpred,lfun)
  
  c(pred.slide,res.slide) %<-% res_prep(pred.slide,lpred,lfun)
  
  
  # Plot expanding
  fig.ex = fig.base
  fig.sl = fig.base
  
  if(is.plot){
  for (n in colnames(pred.expand))
    fig.ex = fig.ex %>% add_trace(x=ts[,xname],y=pred.expand[,n],name = n)
  
  # Plot sliding
  for (n in colnames(pred.slide))
    fig.sl = fig.sl %>% add_trace(x=ts[,xname],y=pred.slide[,n],name = n)
  }
  
  return(list(expanding=list(res=res.expand,fig=fig.ex), sliding = list(res=res.slide,fig=fig.sl)))
}

یک تابع بدرد بخور

این تابع یکسری پارامتر ها رو می تونه فیکس کنه.

f.fix <- function(fname,fixed) {
  variable = c("tr","ts")
  f.new <- function() {}
  formals(f.new) <- setNames(rep(list(bquote()), length(variable)), variable) 

  for(i in variable) assign(i, as.symbol(i))
  body(f.new) <- do.call("call", unlist(list(fname, fixed, mget(variable)),recursive = FALSE))
  
  return(f.new)
}

تشکر از GKI

Polynomial Regression

m.lm_poly = function(tr,ts,n=2,x=NULL){
  # Note that poly() returns Orthogonal Polynomials 
  if (!is.null(x)){ 
    tr = tr[,c("t","c",x),drop=FALSE]
    ts = ts[,c("t",x),drop=FALSE]
  }
  if (n==0)
    m = lm(c~.,tr)
  else
    m = lm(c~poly(t,n)+.,tr)
  return(list(pred = predict(m,ts), extra.info = m))
}

poly.list = list(Linear.Reg=f.fix("m.lm_poly",c(n=1)),
                   Quad.Reg=f.fix("m.lm_poly",c(n=2)),
                   Cubic.Reg=f.fix("m.lm_poly",c(n=3)),
                   Quartic.Reg=f.fix("m.lm_poly",c(n=4)) )
              
LTE.poly = LTE(poly.list,df,percent = 0.8)
LTE.poly$results
     Linear.Reg  Quad.Reg Cubic.Reg Quartic.Reg
RMSE  13660.588 11013.619  8496.516    10426.42
MAD    9939.983  7489.811  7276.125     7721.51

Polynomial Regression (LTE)

LTE.poly$fig
LTE.poly$results
     Linear.Reg  Quad.Reg Cubic.Reg Quartic.Reg
RMSE  13660.588 11013.619  8496.516    10426.42
MAD    9939.983  7489.811  7276.125     7721.51

Polynomial Regression (STE)

STE.poly = STE(poly.list,df)
STE.poly$expanding$res
     Linear.Reg Quad.Reg Cubic.Reg Quartic.Reg
RMSE   12565.93 6430.872  5150.044    5581.286
MAD    11839.20 5114.542  4590.599    5009.681
STE.poly$sliding$res
     Linear.Reg Quad.Reg Cubic.Reg Quartic.Reg
RMSE   2565.268 2274.630  1847.082    1905.489
MAD    2195.257 1914.668  1541.158    1653.001

Polynomial Regression (STE)

STE.poly$expanding$fig
STE.poly$expanding$res
     Linear.Reg Quad.Reg Cubic.Reg Quartic.Reg
RMSE   12565.93 6430.872  5150.044    5581.286
MAD    11839.20 5114.542  4590.599    5009.681

Polynomial Regression (STE)

STE.poly$sliding$fig
STE.poly$sliding$res
     Linear.Reg Quad.Reg Cubic.Reg Quartic.Reg
RMSE   2565.268 2274.630  1847.082    1905.489
MAD    2195.257 1914.668  1541.158    1653.001

ایرادات مدل های رگرسیون چند جمله ای

  1. بی بهره از نعمت فراموشی (بی بنفش)
  2. منحنی پیش بینی شده تعداد متنهی قله دارد

بی بهره از نعمت فراموشی (بی بنفش)

توی این مدل همه داده ها تاثیر یکسانی روی مدل دارند. هرچقدر که این مدل سعی میکنه داده های جدید رو خوب فیت کنه ، همونقدر برای برازش مناسب داده های قدیمی تلاش میکنه! برای همین توی ارزشیابی بلند مدت خیلی خوب عمل نمیکنه!

فراموشی یک نعمت است!

کتاب فارسی نهم دبیرستان!

منحنی پیش بینی شده تعداد متنهی قله دارد

همانطور که می دانید بازار همیشه پستی و بلندی داره! دوره ای نزول میکنه و دوره ای صعود! پس انتظار داریم منحنی پیش بینی شده هم بدون محدودیت ، صعود و نزول کنه و قله هایی رو بسازه. اما یک چند جمله ای درجه n نهایت n-1 قله داره.

مدل رگرسیون فصلی + مدل رگرسیون چند جمله ای

به اختصار به این مدل ها میگیم SP!

Seasonal Polynomial = SP

قبل از انتخاب تعداد فصل ، بد نیست نگاهی به نمودار ACF بندازیم

acf.res = acf(diff(df$c),lag.max = 40)
order(abs(acf.res$acf),decreasing = TRUE)[1:10] -1
 [1]  0 38  2 13 27  5 25 22  7 10

L=38

df$L38 = factor(rep(1:38,length.out=nrow(df)))
head(df,n = 9)
  t     c L38
1 1 105.2   1
2 2 121.5   2
3 3 123.1   3
4 4 122.0   4
5 5 122.0   5
6 6 118.9   6
7 7 122.8   7
8 8 123.0   8
9 9 144.0   9

SP L=38 (LTE)

بیایید L=38 را تست کنیم!

LTE.sp38 = LTE(poly.list,df,percent = 0.8)
LTE.sp38$results
     Linear.Reg  Quad.Reg Cubic.Reg Quartic.Reg
RMSE  13662.879 11010.751  8500.894   10408.777
MAD    9942.056  7485.295  7284.175    7716.033

SP L=38 (LTE)

LTE.sp38$fig
LTE.sp38$results - LTE.poly$results
     Linear.Reg  Quad.Reg Cubic.Reg Quartic.Reg
RMSE   2.291137 -2.868304  4.377488   -17.64842
MAD    2.073230 -4.516408  8.050229    -5.47746

SP L=38 (STE)

STE.sp38 = STE(poly.list,df,sliding.time = 38*2)
STE.sp38$expanding$res
     Linear.Reg Quad.Reg Cubic.Reg Quartic.Reg
RMSE   12743.58 6532.323  5206.721    5641.568
MAD    12007.34 5173.409  4646.200    5070.518
STE.sp38$sliding$res
     Linear.Reg Quad.Reg Cubic.Reg Quartic.Reg
RMSE   5064.047 4634.889  3286.310    3509.706
MAD    4540.562 3897.462  2744.228    2857.289

SP L=38 (STE)

STE.sp38$expanding$fig
STE.sp38$expanding$res - STE.poly$expanding$res
     Linear.Reg  Quad.Reg Cubic.Reg Quartic.Reg
RMSE   177.6497 101.45109  56.67758    60.28267
MAD    168.1405  58.86702  55.60068    60.83673

SP L=38 (STE)

STE.sp38$sliding$fig
STE.sp38$sliding$res - STE.poly$sliding$res
     Linear.Reg Quad.Reg Cubic.Reg Quartic.Reg
RMSE   2498.779 2360.259  1439.228    1604.217
MAD    2345.305 1982.794  1203.070    1204.288

ایرادات مدل های SP

  1. بی بهره از نعمت فراموشی (بی بنفش)
  2. مدل اعتماد به نفس نوسان ندارد!

همونطور که دیدید اضافه کردن روند فصلی به مدل برای این داده ها تاثیری نداشت!

Polynomial Fourier Series Regression = PF

اول از همه، مدل سری فوریه به صورت زیر هست:

\[ Z_t = \alpha_0 + \sum_{i=1}^q(\alpha_iC_i(t)+\beta_iS_i(t)) + e_t \]

به طوری که

\[ S_i(t) = Sin(2\pi f_i t),\space C_i(t) = Cos(2\pi f_i t),\space f_i=i/L \]

حالا به این چند جمله ای اضافه کنید میشه PF.

PF

fsr.x = c()
for (i in 1:4){
  Sname = paste("S",i,"L38",sep = "")
  Cname = paste("C",i,"L38",sep = "")
  fsr.x = c(fsr.x,Sname,Cname)
  df[,Sname] = sin(2*pi*(i/38)*df$t)
  df[,Cname] = cos(2*pi*(i/38)*df$t)
}
head(df)
  t     c L38     S1L38     C1L38     S2L38       C2L38     S3L38       C3L38
1 1 105.2   1 0.1645946 0.9863613 0.3246995  0.94581724 0.4759474  0.87947375
2 2 121.5   2 0.3246995 0.9458172 0.6142127  0.78914051 0.8371665  0.54694816
3 3 123.1   3 0.4759474 0.8794738 0.8371665  0.54694816 0.9965845  0.08257935
4 4 122.0   4 0.6142127 0.7891405 0.9694003  0.24548549 0.9157733 -0.40169542
5 5 122.0   5 0.7357239 0.6772816 0.9965845 -0.08257935 0.6142127 -0.78914051
6 6 118.9   6 0.8371665 0.5469482 0.9157733 -0.40169542 0.1645946 -0.98636130
       S4L38      C4L38
1  0.6142127  0.7891405
2  0.9694003  0.2454855
3  0.9157733 -0.4016954
4  0.4759474 -0.8794738
5 -0.1645946 -0.9863613
6 -0.7357239 -0.6772816

PF (LTE)

pf.list = list(Cubic.H1=f.fix("m.lm_poly",list(n=3,x=fsr.x[1:2])),
                Cubic.H2=f.fix("m.lm_poly",list(n=3,x=fsr.x[1:4])),
                Cubic.H3=f.fix("m.lm_poly",list(n=3,x=fsr.x[1:6])),
                Cubic.H4=f.fix("m.lm_poly",list(n=3,x=fsr.x[1:8]))
                )
LTE.pf = LTE(pf.list,df)
LTE.pf$results
     Cubic.H1 Cubic.H2 Cubic.H3 Cubic.H4
RMSE 8499.544 8500.338 8500.275 8500.616
MAD  7281.397 7282.616 7283.577 7283.477

PF (LTE)

LTE.pf$fig
LTE.pf$results
     Cubic.H1 Cubic.H2 Cubic.H3 Cubic.H4
RMSE 8499.544 8500.338 8500.275 8500.616
MAD  7281.397 7282.616 7283.577 7283.477

PF (STE)

STE.pf = STE(pf.list,df)
STE.pf$expanding$res
     Cubic.H1 Cubic.H2 Cubic.H3 Cubic.H4
RMSE 5151.325 5152.257 5157.345 5161.663
MAD  4595.215 4596.337 4598.468 4604.504
STE.pf$sliding$res
     Cubic.H1 Cubic.H2 Cubic.H3 Cubic.H4
RMSE 2279.960 2335.732 2954.202 5370.195
MAD  1779.177 1766.824 2362.673 4066.471

PF (STE)

STE.pf$expanding$fig
STE.pf$expanding$res
     Cubic.H1 Cubic.H2 Cubic.H3 Cubic.H4
RMSE 5151.325 5152.257 5157.345 5161.663
MAD  4595.215 4596.337 4598.468 4604.504

PF (STE)

STE.pf$sliding$fig
STE.pf$sliding$res
     Cubic.H1 Cubic.H2 Cubic.H3 Cubic.H4
RMSE 2279.960 2335.732 2954.202 5370.195
MAD  1779.177 1766.824 2362.673 4066.471

پول نداری سرمایه گذاری کنی؟

برو کار کن!

برو کار کن!

وضعیت جاب ویژن

پول بیشتر می خوای؟

مدل های بهتری میخوای؟

کتابای بیشتر بخون!

قراره پولدار بشیم!